﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Reflection;
using System.Diagnostics;

namespace PickGold.Base.Proxies
{
	/// <summary>
	/// 代理能用类。
	/// </summary>
	public static class Common
	{
		/// <summary>
		/// 直接Invoke成员
		/// </summary>
		/// <param name="mcm">成员调用消息对象。</param>
		/// <param name="real">要调用的实例，如果是静态方法，则为空。</param>
		/// <param name="method">方法，如果为空则表示为传入消息的成员。</param>
		/// <returns>返回 IMethodReturnMessage 对象。</returns>
		public static IMethodReturnMessage Invoke(this IMethodCallMessage mcm, object real, MethodBase method)//直接访问相同签名的方法。
		{
			if (method == null)
				method = mcm.MethodBase;
			try
			{
				if (method == Reflector.FieldSetter|| method == Reflector.FieldGetter)//【操作】为原对象的成员：=对原对象的成员变量访问
				{
					var args = mcm.Args;
					method.Invoke(real, args);
					return new ReturnMessage(args[args.Length - 1], args, args.Length, null, mcm);
				}

				var o = method.Invoke(real, mcm.Args);
				var os = new ArrayList();
				var ps = mcm.MethodBase.GetParameters();
				for (var i = 0; i < mcm.ArgCount; i++)
				{
					if (ps[i].IsOut || ps[i].ParameterType.IsByRef)
						os.Add(mcm.Args[i]);
				}
				return new ReturnMessage(o, os.ToArray(), os.Count, null, mcm);
			}
			catch (Exception x)
			{
//#if DEBUG
//                if (Debugger.IsAttached)
//                {
//                    if (x.InnerException == null)
//                        Debuger.Write(x);
//                    else
//                        Console.Write(x.InnerException);
//                }
//#endif

				return new ReturnMessage(x.InnerException ?? x, mcm);
			}
		}

		/// <summary>
		/// 直接Invoke相同签名的成员。
		/// </summary>
		/// <param name="mcm">成员调用消息对象。</param>
		/// <param name="real">要调用的实例。</param>
		/// <param name="method">方法，如果为空则表示为传入消息的成员。</param>
		/// <returns>返回 IMethodReturnMessage 对象。</returns>
		public static IMethodReturnMessage Invoke(this IMethodCallMessage mcm, object real, string method)//直接访问相同签名的方法。
		{
			var type = real.GetType();
			var ps = mcm.MethodBase.GetParameters();
			var ts = new Type[ps.Length];
			for (var i = 0; i < ts.Length; i++)
				ts[i] = ps[i].ParameterType;
			if (string.IsNullOrEmpty(method))
				method = mcm.MethodName;
			var m = type.GetMethod(method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, ts, null);
			if (m == null)
				return null;

			if (m.IsStatic)//如果是静态方法，则把实例设为空，以指示调用的是静态方法。
				real = null;
			return mcm.Invoke(real, m);
		}

		/// <summary>
		/// 获取成员变量对象。
		/// </summary>
		/// <param name="mcm">成员调用消息对象。</param>
		/// <param name="type">要获取成员变量所属的申明类型。</param>
		/// <returns>方法表示的成员变量对象，如果此方法不是获取或设置成员变量的方法或方法未找到，则返回空。</returns>
		//public static FieldInfo GetField(this IMethodCallMessage mcm, Type type)
		//{
		//    if (mcm.MethodBase.DeclaringType != typeof(object))
		//        return null;

		//    if (!mcm.MethodBase.IsPrivate)
		//        return null;

		//    if (mcm.Args == null)
		//        return null;

		//    if (mcm.Args.Length != 3)
		//        return null;

		//    if (!(mcm.Args[0] is string))
		//        return null;

		//    if (!(mcm.Args[1] is string))
		//        return null;

		//    if (type == null)
		//        type = mcm.MethodBase.DeclaringType;
		//    return type.GetField(mcm.Args[1] as string, BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
		//}

		//public static PropertyInfo GetProperty(this IMethodCallMessage mcm, Type type)
		//{
		//    return null;
		//}
	}

	/// <summary>
	///远程序列化，WCF序列化
	/// </summary>
	[Serializable]
	class Class
	{
		[NonSerialized]
		protected object _Graph;

		protected Hashtable _Hashtable;

		public Class(object graph)
		{
			this._Graph = graph;
		}

		internal object Graph
		{
			get
			{
				return this._Graph;
			}
			set
			{
				this._Graph = value;
			}
		}
	}
}
